﻿using SkiaSharp.Views.Desktop;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace FAQ_UI
{
	public abstract class SKDrawable : Drawable
	{
		private WriteableBitmap bitmap;

		private bool ignorePixelScaling;
		public SKSize CanvasSize { get; private set; }
		public bool IgnorePixelScaling
		{
			get
			{
				return ignorePixelScaling;
			}
			set
			{
				ignorePixelScaling = value;
				invalidateSelf();
			}
		}
		protected abstract void OnPaintSurface(SKPaintSurfaceEventArgs e);
		public sealed override void draw(DrawingContext drawingContext)
		{
			if (PresentationSource.FromVisual(View) == null)
			{
				return;
			}

			SKSizeI unscaledSize;
			float scaleX;
			float scaleY;
			SKSizeI sKSizeI = CreateSize(out unscaledSize, out scaleX, out scaleY);
			SKSizeI sKSizeI2 = (IgnorePixelScaling ? unscaledSize : sKSizeI);
			CanvasSize = sKSizeI2;
			if (sKSizeI.Width <= 0 || sKSizeI.Height <= 0)
			{
				return;
			}

			SKImageInfo sKImageInfo = new SKImageInfo(sKSizeI.Width, sKSizeI.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
			if (bitmap == null || sKImageInfo.Width != bitmap.PixelWidth || sKImageInfo.Height != bitmap.PixelHeight)
			{
				bitmap = new WriteableBitmap(sKImageInfo.Width, sKSizeI.Height, 96.0 * (double)scaleX, 96.0 * (double)scaleY, PixelFormats.Pbgra32, null);
			}

			bitmap.Lock();
			using (SKSurface sKSurface = SKSurface.Create(sKImageInfo, bitmap.BackBuffer, bitmap.BackBufferStride))
			{
				if (IgnorePixelScaling)
				{
					SKCanvas canvas = sKSurface.Canvas;
					canvas.Scale(scaleX, scaleY);
					canvas.Save();
				}

				OnPaintSurface(new SKPaintSurfaceEventArgs(sKSurface, sKImageInfo.WithSize(sKSizeI2), sKImageInfo));
			}

			bitmap.AddDirtyRect(new Int32Rect(0, 0, sKImageInfo.Width, sKSizeI.Height));
			bitmap.Unlock();
			drawingContext.DrawImage(bitmap, bounds);
		}
		private SKSizeI CreateSize(out SKSizeI unscaledSize, out float scaleX, out float scaleY)
		{
			unscaledSize = SKSizeI.Empty;
			scaleX = 1f;
			scaleY = 1f;
			double actualWidth = bounds.Width;
			double actualHeight = bounds.Height;
			if (!IsPositive(actualWidth) || !IsPositive(actualHeight))
			{
				return SKSizeI.Empty;
			}

			unscaledSize = new SKSizeI((int)actualWidth, (int)actualHeight);
			Matrix transformToDevice = PresentationSource.FromVisual(View).CompositionTarget.TransformToDevice;
			scaleX = (float)transformToDevice.M11;
			scaleY = (float)transformToDevice.M22;
			return new SKSizeI((int)(actualWidth * (double)scaleX), (int)(actualHeight * (double)scaleY));

		}
		static bool IsPositive(double value)
		{
			if (!double.IsNaN(value) && !double.IsInfinity(value))
			{
				return value > 0.0;
			}

			return false;
		}
	}
}
